#include "server.h"


#define REGISTER QString("%register%")
#define LOGIN QString("%login%")
#define REMOVEUR QString("%remove%")
#define CREATE QString("%create%")
#define TERMINATE QString("%terminate%")

static char startChr='@';
static char endChr='!';
static char spacer=',';


Server::Server(int port,QObject *parent) : QObject(parent),
    m_pServer(new QTcpServer())
{
    if(m_pServer->listen(QHostAddress::LocalHost,port))
    {
        qDebug()<<"服务器启动成功..."<<endl;
        m_pQueue= new std::queue<char>();
        connect(m_pServer,&QTcpServer::newConnection,this,&Server::addClient);
    }
}

Server::~Server()
{
    delete m_pQueue;
    m_pServer->close();
    qDeleteAll(m_clients.begin(), m_clients.end());
}
void Server::addClient()
{
    QTcpSocket *client = m_pServer->nextPendingConnection();// get client socket
    m_clients<<client;
    connect(client,SIGNAL(readyRead()),this,SLOT(readBuffer()));
    connect(client,SIGNAL(disconnected()),this,SLOT(removeClient()));
}
void Server::removeClient()
{
    QTcpSocket* leaveClient = qobject_cast<QTcpSocket*>(sender());
    for(auto &c:m_clients)
    {
        if(c==leaveClient)
        {
            leaveClient->close();
            m_clients.removeAll(leaveClient);
            break;
        }
    }
}
void Server::readBuffer()
{
    QTcpSocket* pClient = qobject_cast<QTcpSocket*>(sender());
    if(pClient->state()!=3)
    {
        return;
    }
    for(auto &c:pClient->readAll())
    {
       m_pQueue->push(c);
    }
    QByteArray passage;
    getPassage(passage);
    int task = parsePassage(passage);
    switch (task)
    {
    case 0://register user
    {
        ResigistUser *pRegisThread=new ResigistUser(this);
        connect(pRegisThread,SIGNAL(replyRegisterResult(QTcpSocket*,QString,RegistRes,QByteArray))
                ,this,SLOT(revRegistResult(QTcpSocket*,QString,RegistRes,QByteArray)));
        connect(pRegisThread, &ResigistUser::finished, pRegisThread, &ResigistUser::deleteLater);
        pRegisThread->revPassage(passage,pClient);
        pRegisThread->start();
        break;
    }
    case 1://remove user
    {
        RemoveUser *pRemoveThread=new RemoveUser(this);
        connect(pRemoveThread,SIGNAL(replyRemoveResult(QTcpSocket*,QString,RemoveRes,QByteArray))
                ,this,SLOT(revRemoveResult(QTcpSocket*,QString,RemoveRes,QByteArray)));
        connect(pRemoveThread, &RemoveUser::finished, pRemoveThread, &RemoveUser::deleteLater);
        pRemoveThread->revPassage(passage,pClient);
        pRemoveThread->start();
        break;
    }
    case 2://create vm
    {
        Create *pCreate=new Create(this);
        connect(pCreate,SIGNAL(replyCreateResult(QTcpSocket*,VM,bool,QByteArray))
                ,this,SLOT(revCreateResult(QTcpSocket*,VM,bool,QByteArray)));
        connect(pCreate, &Create::finished, pCreate, &Create::deleteLater);
        pCreate->revPassage(passage,pClient);
        pCreate->start();
        break;
    }
    case 3://delete vm
    {
        TerminateThread *pTerminateThread=new TerminateThread(this);
        connect(pTerminateThread,SIGNAL(replyTerminateResult(QTcpSocket*,QString,QString,QByteArray))
                ,this,SLOT(revTerminateResult(QTcpSocket*,QString,QString,QByteArray)));
        connect(pTerminateThread, &TerminateThread::finished, pTerminateThread, &TerminateThread::deleteLater);
        pTerminateThread->revPassage(passage,pClient);
        pTerminateThread->start();
        break;
    }
    case 4://login user
    {
        LoginThread *pLoginThread=new LoginThread(this);
        connect(pLoginThread,SIGNAL(replyLoginResult(QTcpSocket*,QString,LoginRes,QByteArray))
                ,this,SLOT(revLoginResult(QTcpSocket*,QString,LoginRes,QByteArray)));
        connect(pLoginThread, &LoginThread::finished, pLoginThread, &LoginThread::deleteLater);
        pLoginThread->revPassage(passage,pClient);
        pLoginThread->start();
        break;
    }
    default:
        break;
    }
}
static bool m_revStatus=false;
void Server::getPassage(QByteArray& passage)
{
    while(1)
    {
        if(m_pQueue->size()==0)
        {
            return;
        }
        char temp = m_pQueue->front();//队首元素
        m_pQueue->pop();//去掉对首元素
        if (temp == '@'&&!m_revStatus)//未接收状态下，收到开始标志
        {
            passage.clear();//清空包
            m_revStatus = true;//开启接收
        }
        else if (temp == '!'&&m_revStatus)//接收状态下，收到结束标志
        {
            m_revStatus = false; //关闭接收
            return;
        }
        else if (m_revStatus)//在正常接收状态下
        {
            passage.push_back(temp);
        }
        else//错误状态
        {
            passage.clear();//丢弃这个包
            m_revStatus = false;//关闭接收，等待下一次开启
        }
    }
}
int Server::parsePassage(QByteArray& passage)
{
    if(passage.contains(REGISTER.toLatin1()))
    {
        return 0;
    }
    else if(passage.contains(REMOVEUR.toLatin1()))
    {
        return 1;
    }
    else if(passage.contains(CREATE.toLatin1()))
    {
        return 2;
    }
    else if(passage.contains((TERMINATE.toLatin1())))
    {
        return 3;
    }
    else if(passage.contains(LOGIN.toLatin1()))
    {
        return 4;
    }
    return -1;
}
void Server::revRegistResult(QTcpSocket* socket,QString userLogin,RegistRes res,QByteArray result)
{
    QByteArray buffer;
    buffer.append(startChr).append(REGISTER);
    buffer.append(spacer).append(userLogin);
    switch (res)
    {
    case R_OK:
    {
        buffer.append(spacer).append("success").append(spacer).append('\n').append(result).append(endChr);
        socket->write(buffer);
        break;
    }
    case R_FILE_OPEN_FAILD:
        buffer.append(spacer).append("file open failed").append(spacer).append('\n').append(result).append(endChr);
        socket->write(buffer);
        break;
    case R_LOGIN_EXIST:
        buffer.append(spacer).append("user is exist already").append(spacer).append('\n').append(result).append(endChr);
        socket->write(buffer);
        break;
    case R_OPENSTACK_FAILD:
        buffer.append(spacer).append("openstack failed").append(spacer).append('\n').append(result).append(endChr);
        socket->write(buffer);
        break;
    default:
        break;
    }
}
void Server::revRemoveResult(QTcpSocket* socket,QString userLogin,RemoveRes res,QByteArray result)
{
    QByteArray buffer;
    buffer.append(startChr).append(REMOVEUR);
    buffer.append(spacer).append(userLogin);
    switch (res)
    {
    case M_OK:
        buffer.append(spacer).append("success").append(spacer).append('\n').append(result).append(endChr);
        socket->write(buffer);
        break;
    case M_LOGIN_NOT_EXIST:
        buffer.append(spacer).append("user not exist").append(spacer).append('\n').append(result).append(endChr);
        socket->write(buffer);
        break;
    case M_FILE_OPEN_FAILD:
        buffer.append(spacer).append("file open failed").append(spacer).append('\n').append(result).append(endChr);
        socket->write(buffer);
        break;
    case M_OPENSTACK_FAILD:
        buffer.append(spacer).append("openstack failed").append(spacer).append('\n').append(result).append(endChr);
        socket->write(buffer);
        break;
    case M_PASS_ERROR:
        buffer.append(spacer).append("password is error").append(spacer).append('\n').append(result).append(endChr);
        socket->write(buffer);
        break;
    case M_FORMAT_ERROR:
        buffer.append(spacer).append("file format is error").append(spacer).append('\n').append(result).append(endChr);
        socket->write(buffer);
        break;
    default:
        break;
    }
}
void Server::revLoginResult(QTcpSocket* socket,QString userLogin,LoginRes res,QByteArray result)
{
    QByteArray buffer;
    buffer.append(startChr).append(LOGIN);
    buffer.append(spacer).append(userLogin);
    switch(res)
    {
    case L_OK:
        buffer.append(spacer).append("success").append(spacer).append('\n').append(result).append(endChr);
        socket->write(buffer);
        break;
    case L_FILE_OPEN_FAILED:
        buffer.append(spacer).append("file open failed").append(spacer).append('\n').append(result).append(endChr);
        socket->write(buffer);
        break;
    case L_IDENTITY_ERROR:
        buffer.append(spacer).append("login or password error").append(spacer).append('\n').append(result).append(endChr);
        socket->write(buffer);
        break;
    case L_OPENSTACK_FAILD:
        buffer.append(spacer).append("openstack failed").append(spacer).append('\n').append(result).append(endChr);
        socket->write(buffer);
        break;
    default:
        break;
    }
}
void Server::revCreateResult(QTcpSocket* socket,VM vm,bool res,QByteArray result)
{
    QByteArray buffer;
    buffer.append(startChr).append(CREATE);
    buffer.append(spacer).append(vm.userName);
    buffer.append(spacer).append(vm.vmName);
    buffer.append(spacer).append(vm.vmImage);
    buffer.append(spacer).append(vm.vcpus);
    buffer.append(spacer).append(vm.ram);
    buffer.append(spacer).append(vm.disk);
    buffer.append(spacer).append('\n').append(result);
    buffer.append(endChr);
    socket->write(buffer);
}
void Server::revTerminateResult(QTcpSocket* socket,QString user,QString vmId,QByteArray result)
{
    QByteArray buffer;
    buffer.append(startChr).append(TERMINATE);
    buffer.append(spacer).append(user);
    buffer.append(spacer).append(vmId);
    buffer.append(spacer).append('\n').append(result);
    buffer.append(endChr);
    socket->write(buffer);
}

